/*******************************************************************************
  * @file                   shell.c
  * @Author:                MQjehovah                 mail:MQjehovah@hotmail.com
  * @version                1.0.0
  * @date                   2017.11.22
  * @brief                  
  ******************************************************************************
  * @attention
*******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "shell.h"
#include "ring_buffer.h"
#include "USART.h"
#include "FLASH.h"
#include "delay.h"
#include <stdlib.h>
/* Definition ----------------------------------------------------------------*/
char CMD_LINE_BUF[CMD_REC_BUF_LEN]; //指令接收缓冲区
char *CMDList[] = {                 //指令列表
    "help",
    "list",
    "iap_down",
    "iap_jump_app",
    "iap_over",
    "iap_set_flag",
    "iap_clear_flag"};
/* Functions -----------------------------------------------------------------*/
/*******************************************************************************
  * @brief  shell循环            
  * @param  None              
  * @retval None              
  * @Note   None              
*******************************************************************************/
void shell_loop(void)
{
    while (1)
    {
        char *cmd = shell_readline(CMD_LINE_BUF);
        shell_process(cmd);
        simple_delay_ms(100);
    }
}
/*******************************************************************************
  * @brief  从缓冲区中读取一行指令              
  * @param  None              
  * @retval None              
  * @Note   None              
*******************************************************************************/
char *shell_readline(char *buffer)
{
    // char *p = buffer;
    u32 seek = 0;
    USART_SendStr(SHELL_USART, PROMPT);
    while (1)
    {
        if (rx_buffer.lenth <= 0)
            continue;
        // u8 data = RingBuf_read();
        buffer[seek] = RingBuf_read();
        switch (buffer[seek])
        {
        case '\r': /* Enter */
        case '\n': //回车表示命令输入结束
            USART_SendStr(SHELL_USART, "\r\n");
            if (seek == 0)
                return (char *)-1; //空指令不处理
            buffer[seek] = '\0';   //字符串末尾添加结束符
            // USART_SendStr(SHELL_USART, buffer);
            return buffer;
        case '\0': /* nul */
            continue;
        case 0x03: /* ^C - break */
            //CTRL+C表示取消命令输入
            return ((char *)-1);
        case 0x15: /* ^U - erase line */
            continue;
        case 0x17: /* ^W - erase word */
            //CTRL+W表示删除一个词
            continue;
        case 0x08: /* ^H  - backspace */
        case 0x7F: /* DEL - backspace */
            //表示删除一个字符
            if (seek > 0)
            {
                USART_SendStr(SHELL_USART, "\b \b");
                seek--;
            }
            continue;
        default:
            USART_SendChar(SHELL_USART, buffer[seek]);
            seek++;
            break;
        } //switch
    }
}
/*******************************************************************************
  * @brief  指令处理程序              
  * @param  None              
  * @retval None              
  * @Note   None              
*******************************************************************************/
int shell_process(char *cmd)
{
    static char *argv[CMD_ARG_MAX_CNT] = {0};
    u8 argc = 0;
    argv[argc++] = cmd;

#ifdef DEBUG
    //输出接收到的指令
    USART_SendStr(USART1, "Recieve:");
    USART_SendStr(USART1, cmd);
    USART_SendStr(USART1, "\r\n");
#endif

    if (cmd == (char *)-1) //获取指令数据错误
        return 0;
    //分词
    while (1)
    {
        if (*cmd == '\0')
            break;
        if (*cmd == ' ')
        {
            *cmd = '\0';
            argv[argc++] = ++cmd;
            continue;
        }
        cmd++;
    }

#ifdef DEBUG
    //输出分词后的命令
    USART_SendStr(USART1, "argv[0]:");
    USART_SendStr(USART1, argv[0]);
    USART_SendStr(USART1, "\r\n");
#endif

    if (string_compare(argv[0], "help"))
    {
        USART_SendStr(USART1, "Support Command:\r\n");
        USART_SendStr(USART1, "help:\r\n");
        USART_SendStr(USART1, "echo:   echo what you say.\r\n");
        USART_SendStr(USART1, "time:   show system time.\r\n");
        USART_SendStr(USART1, "info:   show system info.\r\n");
        USART_SendStr(USART1, "read:   read data from address detected.\r\n");
        USART_SendStr(USART1, "reboot: reboot system.\r\n");
        return 1;
    }
    if (string_compare(argv[0], "echo"))
    {
        if (argc > 1)
        {
            USART_SendStr(USART1, argv[1]);
            USART_SendStr(USART1, "\r\n");
        }
        return 1;
    }
    if (string_compare(argv[0], "time"))
    {
        printNumber(USART1, sys_Time, 10);
        USART_SendStr(USART1, "\r\n");
        return 1;
    }
    if (string_compare(argv[0], "info"))
    {
        u32 CpuID[3];
        u32 Lock_Code;
        CpuID[0] = *(u32 *)(0x1ffff7e8);
        CpuID[1] = *(u32 *)(0x1ffff7ec);
        CpuID[2] = *(u32 *)(0x1ffff7f0);
        //加密算法,很简单的加密算法
        Lock_Code = (CpuID[0] >> 1) + (CpuID[1] >> 2) + (CpuID[2] >> 3);
        USART_SendStr(USART1, "Chip Id:0x");
        printNumber(USART1, Lock_Code, 16);
        USART_SendStr(USART1, "\r\n");
        USART_SendStr(USART1, "stack:0x");
        printNumber(USART1, *(u32 *)0x8000000 - __get_MSP(), 16);
        USART_SendStr(USART1, "\r\n");
        return 1;
    }
    if (string_compare(argv[0], "read"))
    {
        u32 addr = 0;
        if (argc > 1)
        {
            if (argv[1][0] == '0' && argv[1][1] == 'x')
            {
                addr = strtol(argv[1], (char **)NULL, 16);
            }
        }
        u32 data = FLASH_Readu32(addr);
        printNumber(USART1, data, 16);
        USART_SendStr(USART1, "\r\n");
        return 1;
    }
    if (string_compare(argv[0], "load"))
    {
        // Ymodem_trans();
        return 1;
    }
    if (string_compare(argv[0], "reboot"))
    {
        __disable_fault_irq();
        NVIC_SystemReset();
        return 1;
    }
    USART_SendStr(USART1, "Unsupport Command\r\n");
    return 0;
}
/*******************************************************************************
  * @brief  字符串比较            
  * @param  None              
  * @retval None              
  * @Note   None              
*******************************************************************************/
u8 string_compare(char *str1, char *str2)
{
    int seek = 0;
    while (1)
    {
        if (str1[seek] == str2[seek])
        {
            if (str1[seek++] == '\0')
                return 1;
            continue;
        }
        return 0;
    }
}
/*******************************************************************************
  * @brief  下载任务函数      
  * @param  None              
  * @retval None              
  * @Note   None              
*******************************************************************************/
// u8 download()
// {
//     RingBuf_flush();              //先清空缓冲区
//     USART_SendChar(USART1, 0x01); //发送开始传输请求
//     USART_SendChar(USART1, 0x02);
//     USART_SendStr(USART1, "download\r\n");
//     USART_SendChar(USART1, 0x03);
//     u8 buffer[64];
//     u16 seek = 0;
//     enum Rec_State
//     {
//         Rec_Idle,
//         Rec_Header,
//         Rec_Text,
//         Rec_End
//     } state;
//     while (1) //程序下载任务
//     {
//         if (rx_buffer.lenth <= 0)
//             continue;
//         u8 data = RingBuf_read();
//         switch (state)
//         {
//         case Rec_Idle:        //空闲待接收
//             if (data == 0x01) //寻找帧头
//                 state = Rec_Header;
//             break;
//         case Rec_Header: //帧头接收
//             if(data==0x02)
//             break;
//         case 0x03: //正文结束

//             break;
//         default: //数据字符

//             break;
//         }
//     }
// }

/*******************************************************************************
  * @brief  Ymodem            
  * @param  None              
  * @retval None              
  * @Note   None              
*******************************************************************************/
// void Ymodem_trans()
// {

//     while (1)
//     {
//         switch (YmodemState)
//         {
//         case YStart:
//         {                                                //通信起始阶段
//             Uart_PutChar(MODEM_C);                       //发起始信号
//             StartChar = Uart_GetCharInTime(100, &Error); //ucos是每秒100个tick，100表示1s，每次等待1s钟。发生超时重发“C”
//             if (Error == OS_ERR_TIMEOUT)
//             {
//                 WaitTime++;
//                 if (WaitTime >= 60)
//                     return 1; //等待60s，超时退出。
//                 continue;     //否则继续，发C。
//             }
//             if (StartChar == MODEM_SOH)
//             {
//                 TempChar = Uart_GetChar();
//                 if (TempChar != 0x00)
//                     return 3; // 不是00序号。
//                 TempChar = Uart_GetChar();
//                 if (TempChar != 0xFF)
//                     return 3; // 不是00序号补码。
//                 for (i = "0"; i < 128; i++)
//                 { //接收数据包0，共128字节
//                     YmodemDev->UserBuf[i] = Uart_GetChar();
//                 }
//                 TempChar = Uart_GetChar();
//                 TempChar = Uart_GetChar(); //丢弃CRC校验，暂时不想实现。
//                 Uart_PutChar(MODEM_ACK);   //发送确认信号。
//                 GetNameAndSize(YmodemDev); //调用子程序，通过缓冲区里的数据获取文件名字符串,以及长度字符串并转换为数据类型。
//                 res = f_open(RecvFile, (const char *)YmodemDev->FileName, FA_READ | FA_WRITE | FA_CREATE_NEW);
//                 YmodemState = YDataTrans; //状态切换到数据传输状态
//                 YmodemDev->NextPackNum = 1;
//                 Uart_PutChar(MODEM_C); //再发一个C，正式启动数据传输 }
//             }
//             break;
//         case YDataTrans:
//         { //数据传输阶段
//             StartChar = Uart_GetChar();
//             switch (StartChar)
//             {
//             case MODEM_EOT:
//             {
//                 YmodemState = YEOT;
//                 Uart_PutChar(MODEM_ACK);
//                 continue;
//             }
//             case MODEM_SOH:
//             {
//                 YmodemDev->PackLen = 128;
//             }
//             break;
//             case MODEM_STX:
//             {
//                 YmodemDev->PackLen = 1024;
//             }
//             break;
//             case MODEM_CANCEL:
//             {
//                 f_unlink(YmodemDev->FileName);
//                 Uart_PutString("用户取消文件传输!\r\n");
//                 return 2;
//             }
//             } //end of switch (StartChar)
//             TempChar = Uart_GetChar();
//             TempChar = Uart_GetChar();
//             for (i = "0"; i < YmodemDev->PackLen; i++)
//             { //接收整个数据包
//                 YmodemDev->UserBuf[i] = Uart_GetChar();
//             }
//             TempChar = Uart_GetChar();
//             TempChar = Uart_GetChar(); //丢弃CRC校验，暂时不想实现。
//             if (ErrorNum == 0)
//             {
//                 res = f_write(RecvFile, (void *)YmodemDev->UserBuf, YmodemDev->PackLen, &ByteWrite); //将接收到得数据写入文件
//                 YmodemDev->NextPackNum++;
//                 Uart_PutChar(MODEM_ACK);
//             } //end of if (ErrorNum == 0 )
//             else
//             {
//                 Uart_PutChar(MODEM_NAK); //接收发现错误，要求重发。 }
//             }
//             break;
//         case YEOT:
//         { //结束传输阶段
//             Uart_PutChar(MODEM_C);
//             StartChar = Uart_GetChar(); //接收起始字符。
//             if (StartChar == MODEM_SOH)
//             {
//                 TempChar = Uart_GetChar();
//                 if (TempChar != 0x00)
//                     return 3; // 不是00序号。
//                 TempChar = Uart_GetChar();
//                 if (TempChar != 0xFF)
//                     return 3; // 不是00序号补码。
//                 for (i = "0"; i < 128; i++)
//                 {
//                     YmodemDev->UserBuf[i] = Uart_GetChar();
//                 }
//                 TempChar = Uart_GetChar();
//                 TempChar = Uart_GetChar(); //丢弃CRC校验，暂时不想实现。
//                 Uart_PutChar(MODEM_ACK);   //发送确认信号。
//                 f_lseek(RecvFile, YmodemDev->FileSize);
//                 f_truncate(RecvFile);
//                 f_close(RecvFile);
//                 return 0;
//             }
//         }
//         default:
//             return 0x20;
//         } //end of switch ( YmodemState );
//         } //end of while (1)
//         }
//     }
    /*********************************END OF FILE**********************************/
